home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 075 (1988-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 075 (1988-11-15)(Ossowski, Stefan)(DE)(PD).adf / VirusX / VirusX.C < prev    next >
C/C++ Source or Header  |  1988-08-14  |  17KB  |  583 lines

  1.  
  2. /* VirusX - by Steve Tibbett
  3.  
  4.     The complete Virus Elimination System!
  5.  
  6.         Please - if you find a new virus, Send me a copy!
  7.         (And warn me it's on the disk!).  I want to keep
  8.         this program current.  (Feel free to put something
  9.         neat (but not copyrighted) on the disk also!)
  10. */
  11.  
  12. /*  History:
  13.  
  14.  A few weeks ago: V1.0 written.
  15. A few days later: V1.01 released - V1.0 wrote garbage when disk was Write Prot. 
  16.        27-Mar-88: V1.2 - Added Byte Bandit RAM detection, and disk detection.  
  17.           (Actually, it's well after Midnight - make that 28-Mar-88)
  18. Just after
  19. uploading V1.2
  20.      to Amic BBS: Realized I put the wrong version in the ARC file - Had to
  21.                   rename V1.2 to V1.21...
  22.  
  23. */
  24.  
  25. /* - Ok, it's not the cleanest code in the world - it was written in two
  26.      days, for a specific purpose, and it works!                         */
  27.  
  28. struct Port *diskport;         /* disk's port.*/
  29. struct IOStdReq *diskreq;    /* disk's IOStdReq */
  30.  
  31. int DisksChecked, DisksInstalled, SCAFound;    /* for title bar info */
  32.  
  33. char titlebuffer[80];
  34.  
  35. /* Who needs includes with Aztec?  Everything's precompiled! */
  36. #include <devices/bootblock.h>
  37. /* Ok, ONE include... */
  38.  
  39. /* Amount of boot code we've got (approx):  */
  40. #define BSIZE 40
  41.  
  42. int ChangeCount[4];        /* TD_CHANGECOUNT for all 4 drives */
  43.  
  44. int LastSum;            /* Used in the checksumming */
  45.  
  46. int CheckDrives;        /* Boolean, from the command line */
  47.  
  48. int error;            /* sort of a temporary variable sort of */
  49.  
  50. unsigned char diskbuffer[3*512];/* Everything ends up in here. 
  51.                    I suppose I should have AllocMem'ed this,
  52.                    but it's SO easy this way */
  53.  
  54. /* Warning messages.  These messages get modified before being displayed
  55.    (Unless you DO have a DF9:) */
  56. char TEXTPTR[] = "Danger:  The disk in DF9: is";
  57. char NBCTEXT[] = "Danger:  The disk in DF9: has";  /* What a waste, eh? */
  58. char CopyText[40];
  59.  
  60. /* This is a byte by byte copy of working boot block code.  Check it
  61.    out if you like.  This is what gets written back to the disk when you
  62.    ask VirusX to fix a disk. */
  63.  
  64. unsigned char bootblock[] = { 'D', 'O', 'S', 0, 0xc0, 0x20, 0x0f, 0x19, 
  65. 0, 0, 3, 0x70, 0x43, 0xfa, 0, 0x18, 
  66. 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68, 
  67. 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 
  68. 0x6f, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,0,0,0,0,0};
  69.  
  70. /* for IntuiText's */
  71. char def_font[] ="topaz.font";
  72.  
  73. struct TextAttr TxtAt_Plain = {    (UBYTE *)def_font, 8,
  74.     FS_NORMAL, FPF_ROMFONT};
  75.  
  76. /***  Non SCA warning requester IntuiText's ***/
  77. struct IntuiText Body2 = {
  78.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *)"Nonstandard Boot Code!", NULL };
  79. struct IntuiText Body1 = {
  80.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)NBCTEXT, &Body2 };
  81. struct IntuiText Pos = {
  82.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Remove it", NULL };
  83. struct IntuiText Neg = {
  84.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Ignore it", NULL };
  85.  
  86. /***** SCA Danger Requester IntuiText's ******/
  87. struct IntuiText SCABody2 = {
  88.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with an SCA Virus!!", NULL };
  89. struct IntuiText SCABody = {
  90.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &SCABody2 };
  91. struct IntuiText SCAPos = {
  92.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Remove it", NULL };
  93. struct IntuiText SCANeg = {
  94.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Ignore it", NULL };
  95.  
  96. /***** BBANDIT Requester IntuiText's ******/
  97. struct IntuiText BBDiskbody3 = {
  98.    0, 1,     JAM2,          20,30,        &TxtAt_Plain, CopyText, NULL };
  99. struct IntuiText BBDiskbody2 = {
  100.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with the Byte Bandit VIRUS!", &BBDiskbody3};
  101. struct IntuiText BBDiskbody = {
  102.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &BBDiskbody2 };
  103.  
  104. /***** BBandit Notice - Removed from Memory ****/
  105. struct IntuiText BBMem3 = {
  106.    0, 1,     JAM2,          20,8,        &TxtAt_Plain,(UBYTE *) "NOTICE:  The Byte Bandit VIRUS was found", NULL };
  107. struct IntuiText BBMem2 = {
  108.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled.  See the", &BBMem3 };
  109. struct IntuiText BBMem1 = {
  110.    0, 1,     JAM2,          20,28,        &TxtAt_Plain,(UBYTE *) "documentation for more information!", &BBMem2 };
  111. struct IntuiText BBMPos = {
  112.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, " Thanks! ", NULL };
  113. struct IntuiText BBMNeg = {
  114.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, " Thanks! ", NULL };
  115.  
  116.  
  117. /***** Write Protect Error Requester IntuiText's ******/
  118. struct IntuiText ERRBody2 = {
  119.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL };
  120. struct IntuiText ERRBody = {
  121.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)"DISK ERROR:  Disk is", &ERRBody2 };
  122. struct IntuiText ERRPos = {
  123.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Retry", NULL };
  124. struct IntuiText ERRNeg = {
  125.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Cancel", NULL };
  126.  
  127. /***** Rewrite block?  Really? ******/
  128. struct IntuiText REWBody3 = {
  129.    0, 1,     JAM2,          20,28,        &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL };
  130. struct IntuiText REWBody2 = {
  131.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3};
  132. struct IntuiText REWBody = {
  133.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)"Are you sure you want to", &REWBody2 };
  134. struct IntuiText REWPos = {
  135.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Yes", NULL };
  136. struct IntuiText REWNeg = {
  137.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "No!", NULL };
  138.  
  139. struct IntuitionBase *IntuitionBase;
  140. struct GfxBase *GfxBase;
  141. struct Window *LittleWindow;
  142. struct IntuiMessage *Message;
  143. struct RastPort *RP;
  144.  
  145. int Keepgoing;        /* a boolean flag.  it's false when we want out. */
  146. int x, y, i;        /* left over from my using Basic */
  147.  
  148. /*** The Newwindow Structure. ***/
  149.  
  150. char TITLETEXT[] = "VirusX 1.21 by Steve Tibbett";
  151. struct NewWindow NewLittleWindow = {
  152.     128,    /* Left, Top, Width, Height */    
  153.     0,        
  154.     309,
  155.     10,        
  156.     0,    /* Frontpen, Backpen */    
  157.     1,        
  158. DISKINSERTED | CLOSEWINDOW | VANILLAKEY | MOUSEBUTTONS,    /* IDCMP Flagz */
  159. WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */    
  160.     NULL,        
  161.     NULL,        
  162.     TITLETEXT,    /* My name.  Dont touch it!! */
  163.     NULL,        
  164.     NULL,        
  165.     0,        
  166.     0,        
  167.     0,        
  168.     0,        
  169.     WBENCHSCREEN,    
  170.     };
  171.  
  172. /*********************Da Beginnin*************************/
  173. main(argc, argv)
  174. int argc;
  175. char *argv[];
  176. {
  177. int OldPri;
  178.  
  179.  
  180. /* Come on, folks, is intuition never NOT going to be available???? */
  181. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  182.  
  183. /* Same with GfxBase.  If GfxBase is gone, we DESERVE to crash. */
  184. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  185.  
  186.  
  187. /* If checkdrives is true, later on it means we want to check all the drives
  188.    with disks in them for viruses. */
  189.  
  190. CheckDrives = TRUE;
  191.  
  192.  
  193. /* Save OldPri so we can restore it later on.  We're so nice. */
  194. OldPri = SetTaskPri(FindTask(0), 19); /* and stick us up high. */
  195. diskport = CreatePort(0,0);
  196. diskreq = CreateStdIO(diskport);
  197.  
  198. SetUp();
  199.  
  200. CheckMemoryForViruses();    /* New to 1.2 - Check is Byte Bandit in RAM? */
  201.  
  202. DoLittle();    /* The main loop.  Do Little.  Ya. */
  203.  
  204. /* restore priorities to saneness, and take off, eh? */
  205. SetTaskPri(FindTask(0), OldPri);
  206.  
  207. DeletePort(diskport);
  208. DeleteStdIO(diskreq);
  209.  
  210. exit(FALSE);
  211. }            
  212.  
  213. /*********************/
  214. DoLittle()
  215. {
  216. register int Code;
  217. register int Class;    /* gee */
  218. register int KG2;    /* KeepGoing 2.  Another booleean. */
  219.  
  220. LittleWindow = OpenWindow(&NewLittleWindow);
  221. if (LittleWindow == NULL) exit(400L);    /* No memory to open little window! */
  222.  
  223. KG2 = TRUE;
  224. RP = LittleWindow->RPort;    /* easier than typing Move(LittleWindow->RP... all
  225.                    the time */
  226. if (CheckDrives == TRUE)    /* Check all drives upon execution (fool */
  227.     {            /* ChangeCount to 1000)          */
  228.     for (x = 0; x < 4; x++) ChangeCount[x] = 1000;
  229.     CheckBlock();        /* CheckBlock() checks boot block for virus. */
  230.     CheckDrives = FALSE;    /* so we don't do it again */
  231.     };
  232.  
  233. SetAPen(RP, 1);
  234. SetBPen(RP, 0);
  235. SetDrMd(RP, JAM2);    /* ya. JAM 2!  Love that name! */
  236.  
  237. while (KG2 == TRUE)
  238.     {
  239.     sprintf(titlebuffer, "VirusX: Disks Checked: %d   Disks Installed: %d   Viruses Found: %d", DisksChecked, DisksInstalled, SCAFound);
  240.     SetWindowTitles(LittleWindow, -1, titlebuffer);
  241.     Message = GetMsg(LittleWindow->UserPort);
  242.     while (Message == NULL)
  243.             {
  244.             /* Lets be nice to other tasks!  Ya! */
  245.             Wait(1<<LittleWindow->UserPort->mp_SigBit);
  246.             Message = GetMsg(LittleWindow->UserPort);
  247.             };
  248.     Class = Message->Class;
  249.     Code = Message->Code;
  250.     if (Message != NULL) ReplyMsg(Message);
  251.     
  252.     if (Class == CLOSEWINDOW) 
  253.         {
  254.         CloseWindow(LittleWindow);
  255.         exit(FALSE);
  256.         };
  257.  
  258.     if (Class == DISKINSERTED) CheckBlock();
  259.     };
  260.  
  261. /* KG2 = false, we fell thru to here.  Ow. */
  262.  
  263. CloseWindow(LittleWindow);
  264. return;
  265. }
  266.  
  267. /**********************/
  268. puts(str)        /* outputs a string, but is REAL small. */
  269. char *str[];
  270. {
  271.     Write(Output(), str, strlen(str));
  272. }
  273.  
  274. /********************/
  275. /* Opens trackdisk, finds out who's out there, and sets Changecount up accordioningly. */
  276. /********************/
  277.  
  278. SetUp()
  279. {
  280.  
  281. for (x = 0; x < 4; x++)    /* go thru all 4 possible drives */
  282.     {
  283.     ChangeCount[x] = 0;
  284.     error = OpenDevice("trackdisk.device",x,diskreq,0);
  285.     if (error > 0) continue;    /* no drive here */
  286.     diskreq->io_Command = TD_CHANGENUM;    
  287.     error = DoIO(diskreq);        
  288.     ChangeCount[x] = diskreq->io_Actual;    /* save changecount for later */
  289.     CloseDevice(diskreq);
  290.     };
  291.  
  292. }
  293.  
  294. /********************************/
  295. /* This routine returns which drive changed disks lately */
  296. /********************************/
  297. WhoChanged()
  298. {
  299. int RetVal;    /* The value we'll return */
  300.  
  301. RetVal = -1;    /* return -1 if all else fails */
  302. for (x = 0; x < 4; x++)
  303.     {
  304.     if (ChangeCount[x] == 0) continue;    /* no drive here */
  305.     error = OpenDevice("trackdisk.device",x,diskreq,0);
  306.     if (error > 0) continue;    /* no drive here */
  307.     
  308.     diskreq->io_Command = TD_CHANGESTATE;
  309.     DoIO(diskreq);
  310.     if (diskreq->io_Actual != 0) 
  311.         {
  312.         continue;
  313.         };
  314.  
  315.     diskreq->io_Command = TD_CHANGENUM;
  316.     DoIO(diskreq);
  317.     if (diskreq->io_Actual != ChangeCount[x]) 
  318.         {
  319.         RetVal = x;
  320.         ChangeCount[x] = diskreq->io_Actual;
  321.         CloseDevice(diskreq);
  322.         goto Out;
  323.         };
  324.     CloseDevice(diskreq);
  325.     };
  326. Out:;
  327. return(RetVal);
  328. }
  329. /********************************/
  330.  
  331. CheckBlock()
  332. {
  333. int Sum, Bootable, Virus;   /* Virus is a flag, Bootable is a flag, Sum the cksum. */
  334. int BBandit;            /* BBandit is a flag too.  Oh well. */
  335. int a, Unit;
  336. int SCA;    /* don't get scared, it's just a flag. */
  337.  
  338. while ((Unit = WhoChanged()) != -1)
  339.  {
  340.  DisksChecked++;
  341.  
  342. SCA = FALSE;
  343. BBandit = FALSE;
  344.  
  345. /* Unit # to open is returned by "WhoChanged()" up above. */
  346. if (Unit == -1) return;
  347. error = OpenDevice("trackdisk.device",Unit,diskreq,0);
  348. if (error > 0) return;
  349.  
  350. /* I've heard stories that pulling a read request to block zero with a
  351.    length of 1024 will cause the virus to write itself back.  Not taking
  352.    any chances. */
  353.  
  354. diskreq->io_Command = CMD_READ;
  355. diskreq->io_Data = diskbuffer;
  356. diskreq->io_Length = 3*512;
  357. diskreq->io_Offset = 0;
  358. DoIO(diskreq);
  359.  
  360. diskreq->io_Length = 0;
  361. diskreq->io_Command = TD_MOTOR;
  362. DoIO(diskreq);                /* turn off motor */
  363.  
  364. if (diskreq->io_Error > 19) return;    /* disk error, lemme out */
  365. CloseDevice(diskreq);
  366.  
  367. Sum = 0;
  368. for (a=0; a<1024; a=a+4)
  369.     {
  370.     LastSum = Sum;
  371.     Sum = Sum + diskbuffer[a+3];
  372.     Sum = Sum + (diskbuffer[a+2] * 256);
  373.     Sum = Sum + (diskbuffer[a+1] * 65536);
  374.     Sum = Sum + (diskbuffer[a] * (65536 * 256));
  375.     if (LastSum > Sum) Sum++;    /* took me a while to figger this out */
  376.     }
  377.  
  378. if (Sum != 0) return;    /* if it's not bootable, we DONT want it! */
  379.  
  380. if (diskbuffer[0x2b] == '9')
  381.     if (diskbuffer[0x2c] == '.')
  382.         if (diskbuffer[0x2d] == '8')
  383.             if (diskbuffer[0x2e] == '7')
  384.                 {
  385.                 SCAFound++;
  386.                 BBandit = TRUE;    /* 9.87 is part of BBandit Virus */
  387.                 };
  388.  
  389. /* check specifically for SCA virus */
  390. if (diskbuffer[8] == 'C')
  391.     if (diskbuffer[9] == 'H')
  392.         if (diskbuffer[10] == 'W')
  393.                 {
  394.                 SCA = TRUE;    /* CHW is part of SCA virus */
  395.                 SCAFound++;
  396.                 };
  397.  
  398. /* compare boot block with real boot block.  If it's not, notify God. */
  399. Virus = FALSE;
  400. for (x = 0; x < 39; x++) /* nuum of lements in bootblock */
  401.     {
  402.     if (diskbuffer[8+x] != bootblock[8+x])
  403.         {    
  404.         Virus = TRUE;
  405.         };
  406.     };
  407.  
  408. /* Oh no, a Virus! */
  409. if (Virus == TRUE) 
  410.     {
  411.     NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
  412.     TEXTPTR[23] = '0'+Unit;
  413.  
  414.     if (SCA == TRUE)
  415.         {
  416.         /* OH NOOOOO, an SCA virus.  Wimpo virus, compared to BBandit */
  417.         Delay(1);
  418.         error = AutoRequest(LittleWindow, &SCABody, &SCAPos, &SCANeg, 0, 0, 320, 70);
  419.         if (error == TRUE) DoInstall(Unit);    /* user wants it fixed. */
  420.         Delay(1);
  421.         }
  422.     else if (BBandit == TRUE)
  423.         {
  424.         /* The Byte Bandit Virus.  Tricky bugger, he WAS. */
  425.         Delay(1);
  426.         sprintf(CopyText, "(Copy Count on this disk: %d)", (diskbuffer[74]*256)+diskbuffer[75]);
  427.         error = AutoRequest(LittleWindow, &BBDiskbody, &SCAPos, &SCANeg, 0, 0, 380, 80);
  428.         if (error == TRUE) DoInstall(Unit); /* User crying for aid */
  429.         Delay(1);
  430.         }
  431.     else 
  432.         {
  433.         /* Probably just a custom boot block (or a new virus...) */
  434.         Delay(1);
  435.         error = AutoRequest(LittleWindow, &Body1, &Pos, &Neg, 0, 0, 320, 70);
  436.         if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
  437.         Delay(1);
  438.         }
  439.     };
  440.  
  441.  
  442. };  /* End of While Whochanged */
  443.  
  444. }
  445.  
  446. /********************************/
  447. /* This is where the boot code gets changed */
  448. /********************************/
  449. DoInstall(un)
  450. int un;    /* unit to write to */
  451. {
  452. register int x;
  453. register int Sum;
  454. int err, a;
  455.  
  456. /* Rewrite disk?  Really?  */
  457. error = AutoRequest(LittleWindow, &REWBody, &REWPos, &REWNeg, 0, 0, 320, 75);
  458. if (error != TRUE) return;    /* user changed his brain. */
  459.  
  460. DisksInstalled++;
  461.  
  462. error = OpenDevice("trackdisk.device", un,diskreq,0);
  463. if (error > 0) return;
  464.  
  465. trygain:
  466.  
  467. diskreq->io_Command = TD_PROTSTATUS;
  468. DoIO(diskreq);        /* check if disk is write protected */
  469.  
  470. if (diskreq->io_Actual != 0)
  471.     {
  472.     error = AutoRequest(LittleWindow, &ERRBody, &ERRPos, &ERRNeg, 0, 0, 280, 75);
  473.     if (error == TRUE) /* error is true or false, depending on user */
  474.         {
  475.         goto trygain;
  476.         };
  477.     CloseDevice(diskreq);
  478.     return;    /* unrecoverable write protect error!!!!!!!!! */
  479.     };
  480.  
  481.  
  482. diskreq->io_Command = CMD_READ;
  483. diskreq->io_Data = diskbuffer;    /* Move the drive head, make some noise so */
  484. diskreq->io_Length = 512;    /* folks know we're doing something. */
  485. diskreq->io_Offset = 44*512;
  486. DoIO(diskreq);
  487.  
  488. for (x = 0; x < 1024; x++)
  489.     diskbuffer[x] = 0;    /* clear diskbuffer to zero.  clean. */
  490.  
  491. for (x = 0; x < 50; x++)
  492.     {
  493.     diskbuffer[x] = bootblock[x];    /* copy boot code into buffer */
  494.     };
  495.  
  496. /* Write it ! */
  497.  
  498.  
  499. diskreq->io_Length = 1024; /* here we go! */
  500. diskreq->io_Data = &diskbuffer[0];  
  501. diskreq->io_Command = CMD_WRITE;
  502. diskreq->io_Offset = 0L;
  503. DoIO(diskreq);
  504.  
  505. diskreq->io_Command = CMD_UPDATE;    /* flush buffer to disk */
  506. DoIO(diskreq);
  507.  
  508. error = diskreq->io_Error;
  509.  
  510. Delay(5);
  511. diskreq->io_Length = 0;
  512. diskreq->io_Command = ETD_MOTOR;
  513. DoIO(diskreq);                /* turn off motor */
  514.  
  515. CloseDevice(diskreq);
  516.  
  517. if (error > 19) 
  518.     {
  519.     SetWindowTitles(LittleWindow, "Error, Nothing Done.", -1);
  520.     } 
  521.     else
  522.     {
  523.     SetWindowTitles(LittleWindow, "Disk Healed.", -1);
  524.     };
  525.  
  526. Delay(100);
  527. SetWindowTitles(LittleWindow, TITLETEXT, -1);
  528.  
  529. }
  530. /************************/
  531.  
  532.  
  533. CheckMemoryForViruses()
  534. {
  535. int VirusBase;    /* ick, whatta name! */
  536. int Temp;
  537. struct ExecBase *ExecBase;
  538. int *LongMemPointer;        /* Used for reading FROM memory */
  539.  
  540. ExecBase = OpenLibrary("exec.library", 0);
  541.  
  542. LongMemPointer = FindName(&ExecBase->DeviceList, "trackdisk.device");
  543.  
  544. Temp = LongMemPointer;
  545. Temp = Temp - 0x1c;
  546. LongMemPointer = Temp;   /* Can't do LongMemPointer - 0x1c because then it's
  547.                 a pointer operation and we get a wrong value     */
  548. VirusBase = (*LongMemPointer) - 0x1b8;
  549.  
  550. LongMemPointer = VirusBase;
  551.  
  552. if (*LongMemPointer == ('D'<<24) + ('O'<<16) + ('S'<<8))    /* klugo */
  553.     {
  554.  
  555.     /* Ok, so we don't really remove it from memory, but we DO render
  556.            it harmless. */
  557.     
  558.     PatchMem(VirusBase+0xaa, 0x4e71);
  559.     PatchMem(VirusBase+0xac, 0x4e71);
  560.     PatchMem(VirusBase+0xae, 0x4e71);
  561.     PatchMem(VirusBase+0xb0, 0x4e71);     /* NOP's */
  562.     PatchMem(VirusBase+0x1c2, 0x6000);    /* Change Bxx to BRA */
  563.     PatchMem(VirusBase+0x2d2, 0x6000);    /* Disable TD and VTI code */
  564.     PatchMem(VirusBase+0x388, 0x4e75);    /* Make sure it doesn't come back */
  565.     PatchMem(VirusBase+0x3ea, 0x0000);    /* Kill resident matchword */
  566.     PatchMem(VirusBase, 0x0000);        /* so WE don't find it again */
  567.     error = AutoRequest(LittleWindow, &BBMem1, &BBMPos, &BBMNeg, 0, 0, 395, 78);
  568.     };
  569.  
  570.  
  571. CloseLibrary(ExecBase);
  572. }
  573.  
  574. /***********************/
  575.  
  576. /**********************/
  577. PatchMem(loc, val)
  578. short *loc;
  579. int val;
  580. {
  581. *loc = val;
  582. }
  583.